本系列文章會在筆者的部落格繼續連載!Design System 101 感謝大家的閱讀!

在 Button 這個系列篇章,我們介紹到了許多先前所提到的觀念,接著來做一個簡單的回顧
第一步: 將 Material Design 中所有的 Reference Token 與 System Token 以 json 的格式匯整到 @ui/design-token裡,並透過 Style Dictionary 產生 CSS 檔
第二步: 建立專門存放 Component Token 以及 Style 的專案 @ui/css,這樣的好處是當今天我們想要換框架時,不需要再重新寫一次 Style,並且不管遷移到任何框架,都可以保持樣式的一致性。
第三步: 核心組件的建立,例如前面章節所提到的 FocusScope, FocusRing 又或是 Slots 這些都是其他組件的基底,而這部通常是最花時間的,但只要基底打好,當建立其他組件時就可以產生飛輪效應。
第四步: 建立共用組件,可能會像是 Button, Badge, Modal 又或是 Carousel 等等的組件,這些會層列在第一線處理各種使用者交互與體驗的場景。
接著讓我們回到 Button 組件的實作吧!
這是整個 Button 組件的關係圖,也是我們在前幾篇提到的
@ui/focus-ring: 讓鍵盤使用者可以透過 focus ring 看到當前被 focus 的組件,而不影響滑鼠使用者。@ui/ripple: 處理點擊按鈕時會出現的波浪紋動畫。@ui/slots: 減少 props 的傳遞,可以透過 <SlotsProvider> 將想客製化的元素傳入。@ui/css: 處理 Button 組件的 Component Token 以及各種交互時的樣式。ui
|-- packages
|   |-- components
|   |   |-- button   <---|
|   |   |-- focus-ring  -|
|   |   |-- ripple      -|
|   |   |-- slots       -|
|   |-- css
|   |   |-- button
@ui/focus-ring (範例程式碼)@ui/ripple: 處理點擊按鈕時會出現的波浪紋動畫。(範例程式碼)@ui/slots: 減少 props 的傳遞,可以透過 <SlotsProvider> 將想客製化的元素傳入。(範例程式碼)@ui/css: 處理 Button 組件的 Component Token 以及各種交互時的樣式。(範例程式碼)最後則是將所有套件引入到 <Button /> 當中
export const Button = React.forwardRef((props, forwardRef) => {
  props = useSlotProps(props, 'button');
  const { variant, children, isDisabled } = props;
  const btnRef = useRef(null);
  const ref = useComposeRef(forwardRef, btnRef);
  return (
    <FocusRing isDisabled={isDisabled}>
      <button
        {...props}
        className={clsx('tocino-Button', { 'is-disabled': isDisabled })}
        data-variant={variant}
        ref={ref}
      >
        <span className="tocino-Button__label">{children}</span>
        <Ripple target={btnRef} />
      </button>
    </FocusRing>
  );
});
所呈現出來的結果

這是 Button 組件大致的實作,當然還有很多細節因為時間的關係沒有辦法一一調整,但希望能夠幫助到大家!